﻿using Luban.DataLoader;
using Luban.Datas;
using Luban.Defs;
using Luban.RawDefs;
using Luban.Types;
using Luban.Utils;
using System.Linq;
using System.Text;
using NLog;
using System;
using System.Collections.Generic;
using System.IO;

namespace Luban.L10N;

/// <summary>
/// 自动生成多语言表的文本提供器
/// 1. 自动收集所有标记为text的字段
/// 2. 生成唯一key：表名_字段名_ID（PascalCase）
/// 3. 使用字段内容作为默认翻译
/// 4. 自动生成多语言表文件
/// </summary>
[TextProvider("autogenerated")]
public class AutoGeneratedTextProvider : ITextProvider
{
    private static readonly Logger s_logger = LogManager.GetCurrentClassLogger();
    
    private readonly Dictionary<string, string> _texts = new();
    private readonly HashSet<string> _unknownTextKeys = new();
    private readonly Dictionary<string, TextRecordInfo> _textRecords = new();
    
    private bool _convertTextKeyToValue;
    private bool _replaceTextWithKey;
    private string _outputPath;
    private string _languageList;
    
    public void Load()
    {
        EnvManager env = EnvManager.Current;
        
        _convertTextKeyToValue = DataUtil.ParseBool(env.GetOptionOrDefault(BuiltinOptionNames.L10NFamily, BuiltinOptionNames.L10NConvertTextKeyToValue, false, "false"));
        _replaceTextWithKey = DataUtil.ParseBool(env.GetOptionOrDefault(BuiltinOptionNames.L10NFamily, BuiltinOptionNames.L10NReplaceTextWithKey, false, "false"));
        
        // 获取输出路径
        _outputPath = env.GetOptionOrDefault(BuiltinOptionNames.L10NFamily, BuiltinOptionNames.L10NTextHydrcatRecordFile, false, "auto_generated_l10n.csv");
        
        // 获取语言列表配置
        _languageList = env.GetOptionOrDefault(BuiltinOptionNames.L10NFamily, BuiltinOptionNames.L10NTextHydrcatLanguageList, false, "zh-CN,en-US");
        
        s_logger.Info("AutoGeneratedTextProvider初始化完成");
        s_logger.Info("输出路径: {}", _outputPath);
        s_logger.Info("语言列表: {}", _languageList);
        s_logger.Info("转换文本键到值: {}", _convertTextKeyToValue);
        s_logger.Info("替换文本为键: {}", _replaceTextWithKey);
    }
    
    public bool ConvertTextKeyToValue => _convertTextKeyToValue;
    
    public bool ReplaceTextWithKey => _replaceTextWithKey;
    
    public Dictionary<string, string> GetTextMapping()
    {
        return new Dictionary<string, string>(_texts);
    }

    public bool IsValidKey(string key)
    {
        return _texts.ContainsKey(key);
    }

    public bool TryGetText(string key, out string text)
    {
        return _texts.TryGetValue(key, out text);
    }
    
    /// <summary>
    /// 收集文本记录信息
    /// </summary>
    public void CollectTextRecords()
    {
        s_logger.Info("开始收集文本记录...");
        
        var visitor = new AutoTextRecordCollectorVisitor();
        var context = new AutoTextRecordContext();
        
        foreach (var table in GenerationContext.Current.Tables)
        {
            s_logger.Info("处理表: {}", table.Name);
            var records = GenerationContext.Current.GetTableAllDataList(table);
            
            foreach (var record in records)
            {
                context.Table = table;
                context.Record = record;
                
                // 遍历记录的所有字段
                record.Data.Apply(visitor, table.ValueTType, context);
            }
        }
        
        // _textRecords是只读字段，不能直接赋值，需要清空后重新添加
        _textRecords.Clear();
        foreach (var record in context.TextRecords)
        {
            _textRecords[record.Key] = record.Value;
        }
        s_logger.Info("文本记录收集完成，共收集 {} 条记录", _textRecords.Count);
    }
    
    /// <summary>
    /// 生成多语言表
    /// </summary>
    public void GenerateL10NTable()
    {
        s_logger.Info("开始生成多语言表...");
        
        var languages = _languageList.Split(',').Select(lang => lang.Trim()).Where(lang => !string.IsNullOrEmpty(lang)).ToList();
        if (languages.Count == 0)
        {
            languages = new List<string> { "zh-CN", "en-US" };
        }
        
        // 构建CSV内容
        var csvContent = new StringBuilder();
        
        // 表头
        csvContent.Append("key");
        foreach (var lang in languages)
        {
            csvContent.Append($",{lang}");
        }
        csvContent.AppendLine();
        
        // 数据行
        foreach (var record in _textRecords.Values.OrderBy(r => r.Key))
        {
            csvContent.Append(record.Key);
            
            // 默认语言使用原始文本内容
            csvContent.Append($",{EscapeCsvValue(record.OriginalText)}");
            
            // 其他语言留空
            for (int i = 1; i < languages.Count; i++)
            {
                csvContent.Append(",");
            }
            csvContent.AppendLine();
        }
        
        // 写入文件
        try
        {
            File.WriteAllText(_outputPath, csvContent.ToString(), Encoding.UTF8);
            s_logger.Info("多语言表已生成: {}", _outputPath);
            s_logger.Info("共生成 {} 条多语言记录", _textRecords.Count);
            // 打印文本键
            s_logger.Info("所有文本键: {}", string.Join(", ", _textRecords.Keys));
        }
        catch (Exception ex)
        {
            s_logger.Error(ex, "生成多语言表失败: {}", _outputPath);
        }
        
        // 构建文本映射（用于运行时查找）
        BuildTextMapping();
    }
    
    private void BuildTextMapping()
    {
        _texts.Clear();
        
        foreach (var record in _textRecords.Values)
        {
            if (_convertTextKeyToValue)
            {
                // 键值转换模式：key -> 翻译文本
                _texts[record.Key] = record.OriginalText;
            }
            else if (_replaceTextWithKey)
            {
                // 文本值到键转换模式：原始文本 -> key
                // 为提高查找性能，同时建立正向和反向映射
                _texts[record.Key] = record.OriginalText;
                _texts[record.OriginalText] = record.Key;
            }
            else
            {
                // 原始模式：key -> 原始文本（用于运行时查找）
                _texts[record.Key] = record.OriginalText;
            }
        }
        
        s_logger.Info("文本映射构建完成，共 {} 条映射", _texts.Count);
        s_logger.Info("映射模式: convertTextKeyToValue={}, replaceTextWithKey={}", _convertTextKeyToValue, _replaceTextWithKey);
    }
    
    private string EscapeCsvValue(string value)
    {
        if (string.IsNullOrEmpty(value))
            return "";
            
        if (value.Contains(",") || value.Contains("\"") || value.Contains("\n") || value.Contains("\r"))
        {
            return $"\"{value.Replace("\"", "\"\"")}\"";
        }
        return value;
    }
    
    public void AddUnknownKey(string key)
    {
        _unknownTextKeys.Add(key);
    }

    public void ProcessDatas()
    {
        // 先收集文本记录
        CollectTextRecords();
        
        // 生成多语言表
        GenerateL10NTable();
        
        // 如果需要转换文本键到值，则进行转换
        if (_convertTextKeyToValue)
        {
            var trans = new TextKeyToValueTransformer(this);
            foreach (var table in GenerationContext.Current.Tables)
            {
                foreach (var record in GenerationContext.Current.GetTableAllDataList(table))
                {
                    record.Data = (DBean)record.Data.Apply(trans, table.ValueTType);
                }
            }
            s_logger.Info("文本键到值转换完成");
        }
        // 如果需要替换文本值为键，则进行转换
        else if (_replaceTextWithKey)
        {
            var trans = new TextValueToKeyTransformer(this);
            foreach (var table in GenerationContext.Current.Tables)
            {
                foreach (var record in GenerationContext.Current.GetTableAllDataList(table))
                {
                    
                    record.Data = (DBean)record.Data.Apply(trans, table.ValueTType);
                }
            }
            s_logger.Info("文本值到键转换完成");
        }
    }
}

/// <summary>
/// 文本记录信息
/// </summary>
public class TextRecordInfo
{
    public string Key { get; set; } = string.Empty;        // 多语言键：表名_字段名_ID
    public string OriginalText { get; set; } = string.Empty; // 原始文本内容
    public string TableName { get; set; } = string.Empty;   // 表名
    public string FieldName { get; set; } = string.Empty;   // 字段名（包含嵌套路径）
    public string RecordId { get; set; } = string.Empty;   // 记录ID
    public string Translation { get; set; } = string.Empty; // 翻译文本（默认为原始文本）
}

/// <summary>
/// 自动文本记录收集上下文
/// </summary>
public class AutoTextRecordContext
{
    public Dictionary<string, TextRecordInfo> TextRecords { get; } = new();
    public DefTable Table { get; set; }
    public Record Record { get; set; }
    public string CurrentFieldPath { get; set; } = "";
    
    public void AddRecord(TextRecordInfo record)
    {
        if (!TextRecords.ContainsKey(record.Key))
        {
            TextRecords[record.Key] = record;
        }
    }
}
